summaryrefslogtreecommitdiff
path: root/app/[lng]/evcp/(evcp)/evaluation-target-list/page.tsx
blob: d60f695a74a44800461c7d8876dec1d6070511fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import * as React from "react"
import { Metadata } from "next"
import { type SearchParams } from "@/types/table"
import { getValidFilters } from "@/lib/data-table"
import { Shell } from "@/components/shell"
import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"
import { HelpCircle } from "lucide-react"
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from "@/components/ui/popover"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"

import { getDefaultEvaluationYear, searchParamsEvaluationTargetsCache } from "@/lib/evaluation-target-list/validation"
import { getEvaluationTargets } from "@/lib/evaluation-target-list/service"
import { EvaluationTargetsTable } from "@/lib/evaluation-target-list/table/evaluation-target-table"

export const metadata: Metadata = {
  title: "협력업체 평가 대상 확정",
  description: "협력업체 평가 대상을 확정하고 담당자를 지정합니다.",
}

interface EvaluationTargetsPageProps {
  searchParams: Promise<SearchParams>
}

// 프로세스 안내 팝오버 컴포넌트
function ProcessGuidePopover() {
  return (
    <Popover>
      <PopoverTrigger asChild>
        <Button variant="ghost" size="icon" className="h-6 w-6">
          <HelpCircle className="h-4 w-4 text-muted-foreground" />
        </Button>
      </PopoverTrigger>
      <PopoverContent className="w-96" align="start">
        <div className="space-y-3">
          <div className="space-y-1">
            <h4 className="font-medium">평가 대상 확정 프로세스</h4>
            <p className="text-sm text-muted-foreground">
              발주실적을 기반으로 평가 대상을 확정하는 절차입니다.
            </p>
          </div>
          <div className="space-y-3 text-sm">
            <div className="flex gap-3">
              <div className="flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
                1
              </div>
              <div>
                <p className="font-medium">발주실적 기반 자동 추출</p>
                <p className="text-muted-foreground">전년도 10월 ~ 해당년도 9월 발주실적에서 업체 목록을 자동으로 생성합니다.</p>
              </div>
            </div>
            <div className="flex gap-3">
              <div className="flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
                2
              </div>
              <div>
                <p className="font-medium">담당자 지정</p>
                <p className="text-muted-foreground">각 평가 대상별로 5개 부서(발주/조달/품질/설계/CS)의 담당자를 지정합니다.</p>
              </div>
            </div>
            <div className="flex gap-3">
              <div className="flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
                3
              </div>
              <div>
                <p className="font-medium">검토 및 의견 수렴</p>
                <p className="text-muted-foreground">모든 담당자가 평가 대상 적합성을 검토하고 의견을 제출합니다.</p>
              </div>
            </div>
            <div className="flex gap-3">
              <div className="flex h-6 w-6 items-center justify-center rounded-full bg-blue-100 text-xs font-medium text-blue-600">
                4
              </div>
              <div>
                <p className="font-medium">최종 확정</p>
                <p className="text-muted-foreground">모든 담당자 의견이 일치하면 평가 대상으로 최종 확정됩니다.</p>
              </div>
            </div>
          </div>
        </div>
      </PopoverContent>
    </Popover>
  )
}

export default async function EvaluationTargetsPage(props: EvaluationTargetsPageProps) {
  const searchParams = await props.searchParams
  const search = searchParamsEvaluationTargetsCache.parse(searchParams)
  const validFilters = getValidFilters(search.filters)

  // 기본 필터 처리 (통일된 이름 사용)
  let basicFilters = []
  if (search.basicFilters && search.basicFilters.length > 0) {
    basicFilters = search.basicFilters
    console.log("Using search.basicFilters:", basicFilters);
  } else {
    console.log("No basic filters found");
  }

  // 모든 필터를 합쳐서 처리
  const allFilters = [...validFilters, ...basicFilters]
     
  // 조인 연산자도 통일된 이름 사용
  const joinOperator = search.basicJoinOperator || search.joinOperator || 'and';

  // 현재 평가년도 (필터에서 가져오거나 기본값 사용)
  const currentEvaluationYear = search.evaluationYear || getDefaultEvaluationYear()

  // Promise.all로 감싸서 전달
  const promises = Promise.all([
    getEvaluationTargets({
      ...search,
      filters: allFilters,
      joinOperator,
    })
  ])

  return (
    <Shell className="gap-4">
      {/* 간소화된 헤더 */}
      <div className="flex items-center justify-between space-y-2">
        <div className="flex items-center justify-between space-y-2">
          <div className="flex items-center gap-2">
            <h2 className="text-2xl font-bold tracking-tight">
              협력업체 평가 대상 확정
            </h2>
            <Badge variant="outline" className="text-sm">
              {currentEvaluationYear}년도
            </Badge>
            <ProcessGuidePopover />
          </div>
        </div>
      </div>
             
      {/* 메인 테이블 (통계는 테이블 내부로 이동) */}
      <React.Suspense 
        key={JSON.stringify(searchParams)} // URL 파라미터가 변경될 때마다 강제 리렌더링
        fallback={
          <DataTableSkeleton
            columnCount={12}
            searchableColumnCount={2}
            filterableColumnCount={6}
            cellWidths={[
              "3rem",   // checkbox
              "5rem",   // 평가년도
              "4rem",   // 구분
              "8rem",   // 벤더코드
              "12rem",  // 벤더명
              "4rem",   // 내외자
              "6rem",   // 자재구분
              "5rem",   // 상태
              "5rem",   // 의견일치
              "8rem",   // 담당자현황
              "10rem",  // 관리자의견
              "8rem"    // actions
            ]}
            shrinkZero
          />
        }
      >
        <EvaluationTargetsTable 
          promises={promises} 
          evaluationYear={currentEvaluationYear}
        />
      </React.Suspense>
    </Shell>
  )
}